package br.com.abril.booking;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.abril.prevision.ExecutivePrevision;
import br.com.abril.prevision.ExecutivePrevisionService;
import br.com.abril.prevision.PrevisionService;
import br.com.abril.wallet.BookingWallet;
import br.com.abril.wallet.BookingWalletRepository;
import br.com.abril.wallet.WalletTeam;

@Service
public class BookingService {

	@Autowired
	private BookingRepository repository;

	@Autowired
	private BookingWalletRepository walletsRepository;

	@Autowired
	private ExecutiveBookingService executiveService;

	@Autowired
	private PrevisionService previsionService;
	
	
	

	@Autowired
	private ExecutivePrevisionService executivePrevisionService;

	@Transactional
	public void save(List<Booking> bookings) {
		repository.save(bookings);
	}

	@Transactional
	public void deleteAll() {
		repository.deleteAllInBatch();
		executiveService.getAll().deleteAllInBatch();
	}

	public BookingRepository getAll() {
		return this.repository;
	}

	public BookingWalletRepository getAllWallets() {
		return this.walletsRepository;
	}

	public Page<BookingWallet> allWalletsByPage(Pageable pageable) {
		return this.walletsRepository.findAll(pageable);
	}

	public ExecutiveBookingService getExecutiveService() {
		return executiveService;
	}

	public List<ExecutiveBooking> findExecutivesByWallet(String wallet) {

		return this.executiveService.getAll()
				.findByWalletOrderByDataReservaDesc(wallet);

	}

	public List<ExecutivePrevision> findExecutivesforPrevisionByWallet(
			String wallet) {
		return this.executivePrevisionService.findExecutivesforPrevisionByWallet(wallet);
	}

	public List<WalletTeam> convertPrevionTeamToWalletTeam(
			List<ExecutivePrevision> previsionTeam) {
		return new WalletTeam().buildPrevisionTeamFrom(previsionTeam);
	}

	public List<WalletTeam> convertBookingTeamToWalletTeam(
			List<ExecutiveBooking> bookingTeam) {
		return new WalletTeam().buildBookingTeamFrom(bookingTeam);
	}

	public boolean compareWalletTeams(List<WalletTeam> bookingTeam,
			List<WalletTeam> previsionTeam) {
		return bookingTeam.equals(previsionTeam);
	}

	public boolean executiveBookingTeamIsEqualsPrevision(
			List<ExecutiveBooking> bookingTeam,
			List<ExecutivePrevision> previsionTeam) {
		return compareWalletTeams(
				convertPrevionTeamToWalletTeam(previsionTeam),
				convertBookingTeamToWalletTeam(bookingTeam));
	}

	public boolean previsionTeamIsAfterThanBooking(
			List<ExecutivePrevision> previsionTeam,
			List<ExecutiveBooking> bookingTeam) {
		if (previsionTeam.isEmpty() || bookingTeam.isEmpty() ) return false;
		
		ExecutivePrevision lastPrevisionForWallet = previsionTeam.get(0);
		ExecutiveBooking lastBookingForWallet = bookingTeam.get(0);

		if (lastPrevisionForWallet == null
				|| lastBookingForWallet.getBookingDate() == null)
			return false;

		return lastPrevisionForWallet.getBookingDate().after(
				lastBookingForWallet.getBookingDate());
	}

	public List<ExecutiveBooking> filterTeamByLastBooking(String lastPrevision,
			List<ExecutiveBooking> executives) {
		return indexExecutivesForBooking(executives).get(lastPrevision);
	}

	public Map<String, List<ExecutiveBooking>> indexExecutivesForBooking (List<ExecutiveBooking> executives) {

		Map<String, List<ExecutiveBooking>> indexed = new HashMap<String, List<ExecutiveBooking>>();
		for (ExecutiveBooking executive : executives) {
			if (!indexed.containsKey(executive.getReserva__c())) {
				indexed.put(executive.getReserva__c(),
						new ArrayList<ExecutiveBooking>());
			}
			indexed.get(executive.getReserva__c()).add(executive);
		}
		return indexed;

	}
	
	public List<ExecutivePrevision> filterTeamByLastPrevison(String lastPrevision , List<ExecutivePrevision> executives) {
		return previsionService.indexExecutivesForPrevision(executives).get(lastPrevision);
	}
		
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void updateExecutiveBookingsWithError ( List<ExecutiveBooking> executives , Exception exception ) {
		for (ExecutiveBooking executive : executives) {
			executive.setJobExecutionStatus( "UPLOADING_ERROR" );
			executive.setJobExecutionExceptionInfo( exception.getMessage() );
		}
		executiveService.save(executives);
	}


	

}
